home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 16
/
CU Amiga Magazine's Super CD-ROM 16 (1997-10-16)(EMAP Images)(GB)[!][issue 1997-11].iso
/
CUCD
/
Online
/
HBBS
/
Source
/
Library
/
HBBSCommon.c_pre_21-NOV-9
< prev
next >
Wrap
Text File
|
1997-08-22
|
64KB
|
2,489 lines
/*
todo
====
remove LIBCountListItems(), replace with HBBS_NodesInList() :-)
*/
#define HBBSCOMMON
#define MAIN
#include <ctype.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/exec.h>
#include <exec/types.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <dos/filehandler.h>
#include <dos/dosextens.h>
#include <libraries/reqtools.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <clib/reqtools_protos.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/reqtools.h>
#include "/common/types.h"
#include "/common/errors.h"
#include "/common/defines.h"
#include "/common/structures.h"
#include "/common/strings.h"
#include "/common/files.h"
#include "/common/release.h"
// some forward defines
void __asm __saveds LIBstrNcpy(register __a0 UBYTE *dest,register __a1 UBYTE *source,register __d0 int chars);
void __asm __saveds LIBHBBS_rterror(register __a0 char *str);
BOOL __asm __saveds LIBAssignOK(register __a0 char *checkme );
BOOL __asm __saveds LIBHBBS_AddCfgItem(register __a0 struct CfgFileData *cfgfile,register __a1 UBYTE *itemname,register __a2 UBYTE *params);
struct List __asm __saveds *LIBHBBS_CreateList( void );
void __asm __saveds LIBHBBS_DateStrFromTM(register __a0 UBYTE *datestr, register __a1 struct tm *timestruct);
V_BOOL __asm __saveds LIBHBBS_AddCfgItemQuick(register __a0 struct CfgFileData *cfgfile,register __a1 char *ItemName, register __a2 char *Params);
void __asm __saveds LIBHBBS_FlushConfig(register __a0 struct CfgFileData *cfgfile);
BOOL __asm __saveds LIBPathOK(register __a0 char *str);
// needed libs..
struct DosLibrary *DOSBase=NULL;
struct ExecBase *SysBase=NULL;
struct ReqToolsBase *ReqToolsBase=NULL;
char *versionstr="$VER: HBBSCommon.library "RELEASE_STR;
// global variables.. (keep to a minimum..)
struct BBSGlobalData *BBSGlobal=NULL;
UBYTE *OPT_PRIV_LastUserNum="LastUserNum";
UBYTE *OPT_PRIV_CallsEver="CallsEver";
char monthstr[12][4]={"JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"};
// actual functions..
void __asm __saveds LIBFreeStr(register __a0 char *str)
{
if (str) FreeVec(str);
}
char __asm __saveds *LIBDupStr(register __a0 char *str)
{
char *newstr=NULL;
if (str)
{
if (newstr=(char *)AllocVec(strlen(str)+1,MEMF_PUBLIC))
{
newstr[0]=0;
strcpy(newstr,str);
}
}
return(newstr);
}
char __asm __saveds *LIBFreeAndSet(register __a0 char **varname,register __a1 char *newstr)
{
// this routines frees memory allocated to strings using strdup or
// and duplicates the string in newstr and sets varname to the newly allocated str
if (*varname!=NULL)
{
LIBFreeStr(*varname);
*varname=NULL;
}
if (newstr)
{
*varname=LIBDupStr(newstr);
}
return(*varname); // return varname if you want to test result..
}
V_BOOL __asm __saveds LIBCheckBoolean(register __a0 char *str)
{
if (stricmp(str,"TRUE")==0 || stricmp(str,"ON")==0 || stricmp(str,"YES")==0)
return(TRUE);
else
return(FALSE);
}
// creates a new node with ln_Name set to a copy of str, and appends it to the list specified
V_ERROR __asm __saveds LIBNewStrNode(register __a0 char *str,register __a1 struct List *list)
{
struct Node *NewNode;
V_ERROR retval=TYPE_MEMORY;
if (NewNode=AllocVec(sizeof(struct Node),MEMF_PUBLIC))
{
if (NewNode->ln_Name=LIBDupStr(str))
{
AddTail(list,NewNode);
retval=ERR_NO_ERROR;
}
else
{
FreeVec(NewNode);
}
}
return(retval);
}
void __asm __saveds LIBUpperCase(register __a0 char *str)
{
// converts str into uppercase
short loop;
for (loop=0;str[loop];loop++) str[loop]=toupper(str[loop]);
}
char __asm __saveds *LIBupcase(register __a0 char *str)
{
// converts str into uppercase and returns a pointer to a new
// string.
// returns NULL if it fails.
// dont forget to FreeStr() the output!
char *outstr;
short loop;
if (outstr=LIBDupStr(str))
{
for (loop=0;str[loop];loop++) outstr[loop]=toupper(str[loop]);
}
return(outstr);
}
short __asm __saveds LIBposition(register __a0 char *substr,register __a1 char *str)
{
// returns an character offset of a substring in a string
// this version is CASE SENSITIVE
// returns -1 if substring not found in the string
char *whstr;
return((short)((whstr=strstr(str,substr)) ? (short)((LONG)whstr-(LONG)str) : -1));
}
short __asm __saveds LIBiposition(register __a0 char *substr,register __a1 char *str)
{
// returns an character offset of a substring in a string
// this version is CASE INSENSITIVE
// returns -1 if substring not found in the string
// or -2 if memory allocation error
short where=-2;
char *isubstr,*istr;
if (isubstr=LIBupcase(substr))
{
if (istr=LIBupcase(str))
{
where=LIBposition(isubstr,istr);
LIBFreeStr(istr);
}
LIBFreeStr(isubstr);
}
return(where);
}
void __asm __saveds LIBstrfcpy(register __a0 char *dest,register __a1 char *source,register __d0 int from)
{
/*
copy all chars from "source" to "dest" starting at offset "from"
(kinda the reverse from strncpy() )
*/
int loop=from,pos=0;
if (from<=strlen(source)-1)
{
while (source[loop])
{
dest[pos]=source[loop];
loop++;
pos++;
}
}
dest[pos]=0;
}
void __asm __saveds LIBstripcr(register __a0 char *s)
{
/* New Optimized Version 04-JAN-1996 */
LONG Len;
if (s)
{
Len=strlen(s)-1; // set to point to last char in string 's'
while (Len>=0 && (s[Len]=='\r' || s[Len]=='\n'))
{
s[Len--]=0; // string is now 1 char smaller, and overwrite the \r or \n with a null terminator
}
}
}
/* old version, had problems with small strings!
void __asm __saveds LIBstripcr(register __a0 char *s)
{
// caters for \n or \r or \r\n or \n\r :-)
short sl;
sl=strlen(s);
if (s[sl-1]==10 || s[sl-1]==13) s[sl-1]=0;
sl=strlen(s);
if (s[sl-1]==10 || s[sl-1]==13) s[sl-1]=0;
// hmm ? how about a for next loop there ? nah, bigger.. slower...
}
*/
UBYTE __asm __saveds *LIBStripComments(register __a0 char *s)
{
/* New Optimized Version 04-JAN-1996 */
// returns a pointer to the start of the comments too..
UBYTE *strptr;
if (strptr=strchr(s,';'))
{
*strptr=0;
strptr++; //we've just killed the ';' so point to next char..
}
return(strptr);
}
/* older version. allocated memory!!
UBYTE __asm __saveds *LIBStripComments(register __a0 char *s)
{
// returns a pointer to the start of the comments too..
int where;
if ((where=LIBposition(";",s))>=0)
{
s[where]='\0';
return(&s[where+1]); // return pointer to character after the ; in the string
}
return(NULL);
}
*/
void __asm __saveds LIBStripSpaces(register __a0 char *s)
{
/* New Optimized Version 04-JAN-1996 */
/* this version only parses the string once, much nicer.. */
LONG len=strlen(s)-1;
// while the last char is a ' ', set it to a 0
while (len>=0 && s[len]==' ') s[len--]=0; // cooler Kompakt coding! :-)
}
/* old version, too slow, keeps parsing strings..
void __asm __saveds LIBStripSpaces(register __a0 char *s)
{
// while the last char is a ' ', set it to a 0
while (s[strlen(s)-1]==' ') s[strlen(s)-1]=0; // Kompakt coding! :-)
}
*/
void __asm __saveds LIBreplace(register __a0 char *dest,register __a1 char *compare,register __a2 char *from,register __a3 char *to)
{
/*
replace all occurences of "from" in "compare" with "to" and store result in "dest"
(note: this is dead usefull!!!)
e.g. replace(dest,source,"Whops","Whoops!");
compare and dest can be the same variable...
*/
int where;
char *mystring;
if (mystring=LIBDupStr(compare))
{
strcpy(dest,"");
do
{
where=LIBposition(from,mystring);
if (where!=-1)
{
strncat(dest,mystring,where); /* copy first part of string */
strcat(dest,to); /* add repeaced chars */
LIBstrfcpy(mystring,mystring,where+strlen(from)); /* copy rest of string so we find first position of from */
}
} while (where!=-1); /* keep doing until "from" is not found */
strcat(dest,mystring); /* add the rest of the string */
LIBFreeStr(mystring);
}
}
BOOL __asm __saveds LIBGetParams(register __a0 char *dest,register __a1 char *source)
{
UBYTE *strptr;
dest[0]=0;
if (strptr=strchr(source,'='))
{
strcpy(dest,strptr+1);
return(TRUE);
}
return(FALSE);
}
/* old version, shite...
BOOL __asm __saveds LIBGetParams(register __a0 char *dest,register __a1 char *source)
{
int where;
dest[0]=0;
// if ( ((where=LIBposition("=",source))!=-1) && (where!=(strlen(source)-1)) )
if ((where=LIBposition("=",source))>=0)
{
LIBstrfcpy(dest,source,where+1);
return(TRUE);
}
return(FALSE);
}
*/
BOOL __asm __saveds LIBGetItem(register __a0 char *dest,register __a1 char *source)
{
int loop=0;
// increment start counter until we encounter a character that's not a space or tab
while (source[loop]==' ' || source[loop]==8) loop++;
while (source[loop] && source[loop]!='=') // not end of string && '=' ?
{
dest[loop]=source[loop];
loop++;
}
dest[loop]='\0';
if (dest[0]!=0) return(TRUE);
return(FALSE);
}
void __asm __saveds LIBGetNumber(register __a0 int *num,register __a1 char *item)
{
int where;
char numstr[5];
for (where=strlen(item);isdigit(item[where-1]);where--);
LIBstrfcpy(numstr,item,where);
*num=atoi(numstr);
}
ULONG __asm __saveds LIBSafePutToPort(register __a0 struct Message *message, register __a1 STRPTR portname)
{
struct MsgPort *port;
Forbid();
if (port=FindPort(portname))
{
PutMsg(port,message);
}
Permit();
return((ULONG)port);
}
// new: if message you are sending has a reply port, it'll return a pointer to the replied
// message, other wise it'll return 1.
// it will ALWAYS return NULL if it fails to send the message tho..
struct Message __asm __saveds *LIBSendMessage(register __a0 struct Message *Msg,register __a1 char *MPortName)
{
// BOOL waitforreply=(Msg->mn_ReplyPort) ? TRUE : FALSE;
if (LIBSafePutToPort(Msg,MPortName))
{
// if (waitforreply)
if (Msg->mn_ReplyPort)
{
if (1L << Msg->mn_ReplyPort->mp_SigBit==Wait(1L << Msg->mn_ReplyPort->mp_SigBit))
{
return(GetMsg(Msg->mn_ReplyPort));
}
}
else return((struct Message *)1L);
}
return(NULL);
}
V_BIGNUM __asm __saveds LIBCountListItems( register __a0 struct List *list)
{
V_BIGNUM retval=0;
struct Node *node;
if (list)
{
for (node = list->lh_Head ; node->ln_Succ ; node =node->ln_Succ)
{
retval++;
}
}
return(retval);
}
void __asm __saveds LIBFreeStrList(register __a0 V_STRINGLIST strlist)
{
// free all strings in a list and remove all nodes from the list.
// then free the nodes and the list itself..
struct Node *node;
if (strlist)
{
while (strlist->lh_Head->ln_Succ)
{
node=strlist->lh_Head;
LIBFreeStr(node->ln_Name);
Remove(node);
FreeVec(node);
}
FreeVec(strlist);
}
}
struct BBSGlobalData __asm __saveds *LIBHBBS_GimmeBBS( void )
{
return(BBSGlobal);
}
void __asm __saveds LIBHBBS_SetBBS(register __a0 struct BBSGlobalData *B)
{
BBSGlobal=B;
}
struct Node __asm __saveds *LIBGetNode(register __a0 struct List *lh,register __d0 UWORD n)
{ // starts from 0, 0 being the first node in the list..
// thanks to the author of YAK for this and the next function..
struct Node *ln;
for (ln = lh->lh_Head; n--; ln = ln->ln_Succ);
return ln;
}
UWORD __asm __saveds LIBGetNodeNum(register __a0 struct List *lh,register __a1 struct Node *node)
{
struct Node *ln;
UWORD i;
for (i = 0, ln = lh->lh_Head; ln != node; ln = ln->ln_Succ, i++);
return i;
}
struct NodeData __asm __saveds *LIBHBBS_NodeDataPtr(register __d0 short nodenum)
{
struct NodeData *nd;
for (nd = (struct NodeData *)BBSGlobal->NodeList->lh_Head ; nd->node.ln_Succ ; nd =(struct NodeData *) nd->node.ln_Succ)
{
if (nd->NodeNum==nodenum) return(nd);
}
return(NULL);
}
V_ERROR __asm __saveds LIBHBBS_LogError(register __a0 V_STRING filename,register __d0 V_ERROR errnum,register __a1 V_STRING string,register __d1 V_ERROR errtype)
{
// this function returns the parameter errnum supplied and unmodified.
BPTR FH;
V_STRING errstr;
struct tm *tp;
long t;
if (filename)
{
if (FH=Open(filename,MODE_READWRITE))
{
Seek(FH,0,OFFSET_END);
if (errstr=AllocVec(BIG_STR,MEMF_PUBLIC))
{
time(&t);
tp=localtime(&t);
sprintf(errstr,"%s %s: ",asctime(tp),TYPE_STR[errtype]);
Write(FH,errstr,strlen(errstr)); // don't care if it fails.. (could be diskfull :-)
switch(errnum)
{
case ERR_ERROR_OPENING:
sprintf(errstr,"Error opening the file -> %s",string);
break;
case ERR_ERROR_READING:
sprintf(errstr,"Error reading the file -> %s",string);
break;
case ERR_ERROR_WRITING:
sprintf(errstr,"Error writing the file -> %s",string);
break;
case ERR_NODESETTINGS:
strcpy(errstr,"NodeLocal File Error");
break;
case ERR_GENERAL:
strcpy(errstr,string);
break;
case ERR_DOORTIMEOUT:
sprintf(errstr,"Timout Occured When Loading Door -> %s",string);
break;
default:
sprintf(errstr,"Unknown Error!");
break;
}
Write(FH,errstr,strlen(errstr));
Write(FH,"\n",1);
FreeVec(errstr);
}
Close(FH);
}
}
return(errnum);
}
/*
// lets play spot the bug that cuases this routine to crash the system..
// 5 quid goes to the person the finds the problem!!
struct CfgFileData __asm __saveds *LIBHBBS_LoadConfig(register __a0 UBYTE *filename,register __d0 ULONG Flags)
{
// New Optimized Version 04-JAN-1996
BPTR FH;
LONG found=0;
UBYTE buffer[BIG_STR+1];
UBYTE ItemName[BIG_STR+1];
UBYTE Params[BIG_STR+1];
struct CfgFileData *cfgfile=NULL;
struct CfgItemData *node=NULL;
if (LIBPathOK(filename))
{
// create and init our CfgFileData structure..
if (cfgfile=AllocVec(sizeof(struct CfgFileData),MEMF_PUBLIC|MEMF_CLEAR))
{
cfgfile->filename=LIBDupStr(filename);
if (cfgfile->ItemsList=LIBHBBS_CreateList())
{
if (FH=Open(filename,MODE_OLDFILE))
{
while (FGets(FH,buffer,BIG_STR))
{
LIBstripcr(buffer);
ItemName[0]=0;
Params[0]=0;
LIBStripComments(buffer);
LIBStripSpaces(buffer);
if (LIBGetItem(ItemName,buffer))
{
if (LIBGetParams(Params,buffer))
{
if (node=AllocVec(sizeof(struct CfgItemData),MEMF_PUBLIC))
{
node->node.ln_Name=LIBDupStr(ItemName); // *C* add errorchecking..
node->Params=LIBDupStr(Params);
AddTail(cfgfile->ItemsList,(struct Node*)node);
found++;
}
// if (LIBHBBS_AddCfgItemQuick(cfgfile,ItemName,Params))
// {
// found++;
// }
}
}
}
Close(FH);
}
}
if (!found)
{
LIBHBBS_FlushConfig(cfgfile);
cfgfile=NULL;
}
}
}
return(cfgfile);
}
*/
struct CfgFileData __asm __saveds *LIBHBBS_LoadConfig(register __a0 UBYTE *filename,register __d0 ULONG Flags)
{
BPTR FH;
struct FileInfoBlock *FIB;
LONG nr;
UBYTE *Data;
ULONG Length;
V_BOOL done,nearlydone;
LONG filepos=0,bufferpos,found=0;
V_STRING buffer;
V_STRING ItemName;
V_STRING Params;
struct CfgItemData *node;
struct CfgFileData *cfgfile=NULL;
if (FH=Open(filename,MODE_OLDFILE))
{
if (cfgfile=AllocVec(sizeof(struct CfgFileData),MEMF_PUBLIC|MEMF_CLEAR))
{
if (FIB=(struct FileInfoBlock *)AllocVec(sizeof(struct FileInfoBlock),MEMF_PUBLIC))
{
ExamineFH(FH,FIB);
Length=FIB->fib_Size;
if (Data=AllocVec(Length,MEMF_PUBLIC))
{
if ((nr=Read(FH,Data,Length))!=Length)
{
LIBHBBS_LogError(BBSGlobal->ErrorLogFile,ERR_ERROR_READING,filename,TYPE_CRITICAL);
}
else
{
if (cfgfile->ItemsList=LIBHBBS_CreateList())
{
buffer=AllocVec(BIG_STR,MEMF_PUBLIC);
ItemName=AllocVec(BIG_STR,MEMF_PUBLIC);
Params=AllocVec(BIG_STR,MEMF_PUBLIC);
if (buffer && ItemName && Params)
{
do
{
bufferpos=0;
done=FALSE;
nearlydone=FALSE; // :-) love those variable names! :-)
do
{
if (Data[filepos]=='\r' || Data[filepos]=='\n')
{
nearlydone=TRUE;
filepos++;
}
else
{
if (nearlydone)
{
done=TRUE;
}
else
{
buffer[bufferpos]=Data[filepos];
filepos++;
bufferpos++;
}
}
} while (filepos<Length && !done && bufferpos<BIG_STR-2); // 1 for null and 1 more cos we still have to add the null
buffer[bufferpos]=0;
ItemName[0]=0; // null terminate both strings..
Params[0]=0;
if (!(Flags & LCFG_NOSTRIPCOMMENTS)) LIBStripComments(buffer);
if (!(Flags & LCFG_NOSTRIPSPACES)) LIBStripSpaces(buffer);
if (LIBGetItem(ItemName,buffer))
{
if (LIBGetParams(Params,buffer))
{
if (node=AllocVec(sizeof(struct CfgItemData),MEMF_PUBLIC))
{
node->node.ln_Name=LIBDupStr(ItemName); // *C* add errorchecking..
node->Params=LIBDupStr(Params);
AddTail(cfgfile->ItemsList,(struct Node*)node);
found++;
}
}
}
} while (filepos<Length);
}
if (Params) FreeVec(Params);
if (ItemName) FreeVec(ItemName);
if (buffer) FreeVec(buffer);
}
}
FreeVec(Data);
}
FreeVec(FIB);
}
if (found)
{
cfgfile->filename=LIBDupStr(filename);
}
else
{
LIBHBBS_FlushConfig(cfgfile);
cfgfile=NULL; // just to make sure.. *C* ?? needed ?
}
}
Close(FH);
}
return(cfgfile);
}
void __asm __saveds LIBHBBS_FlushConfig(register __a0 struct CfgFileData *cfgfile)
{
struct CfgItemData *node;
if (cfgfile)
{
while ((cfgfile->ItemsList) && (cfgfile->ItemsList->lh_Head->ln_Succ))
{
node=(struct CfgItemData *)cfgfile->ItemsList->lh_Head;
LIBFreeStr(node->node.ln_Name);
LIBFreeStr(node->Params);
Remove((struct Node *)node);
FreeVec(node);
}
FreeVec(cfgfile->ItemsList);
LIBFreeStr(cfgfile->filename);
FreeVec(cfgfile);
}
}
V_BOOL __asm __saveds LIBHBBS_SaveConfig(register __a0 struct CfgFileData *cfgfile)
{
// returns TRUE on successful completion.
BPTR FH;
struct CfgItemData *node;
char outstr[BIG_STR];
if (LIBAssignOK(cfgfile->filename))
{
if (FH=Open(cfgfile->filename,MODE_NEWFILE))
{
for (node = (struct CfgItemData*)cfgfile->ItemsList->lh_Head ; node->node.ln_Succ ; node =(struct CfgItemData *)node->node.ln_Succ)
{
sprintf(outstr,"%s=%s\n",node->node.ln_Name,node->Params);
Write(FH,outstr,strlen(outstr));
}
Close(FH);
return(TRUE);
}
}
return(FALSE);
}
struct CfgItemData __asm __saveds *LIBHBBS_GetCfgNode(register __a0 struct CfgFileData *cfgfile,register __a1 V_STRING optionstr)
{
struct CfgItemData *Item;
for (Item = (struct CfgItemData *)cfgfile->ItemsList->lh_Head ; Item->node.ln_Succ ; Item =(struct CfgItemData *) Item->node.ln_Succ)
{
if (stricmp(optionstr,Item->node.ln_Name)==0)
{
return(Item);
}
}
return(NULL);
}
V_SMALLNUM __asm __saveds LIBHBBS_GetSetting(register __a0 struct CfgFileData *cfgfile,register __a1 void **result,register __d0 V_FLAGS optiontype,register __a2 V_STRING optionstr,register __d1 V_BOOL multi)
{
// returns the amount of items found (1 for non multi, >0 for multi, 0 for none)
V_SMALLNUM found=0;
V_STRING CompareStr;
struct Node *node;
struct CfgItemData *Item;
// allocate a big string for comparing the strings..
if (CompareStr=AllocVec(BIG_STR,MEMF_PUBLIC))
{
// parse list..
for (Item = (struct CfgItemData *)cfgfile->ItemsList->lh_Head ; Item->node.ln_Succ ; Item =(struct CfgItemData *) Item->node.ln_Succ)
{
if (multi==OPT_MULTI)
{
sprintf(CompareStr,"%s_%d",optionstr,found+1);
}
if ((multi==OPT_SINGLE) && (stricmp(optionstr,Item->node.ln_Name)==0) ||
(multi==OPT_MULTI) && (stricmp(CompareStr,Item->node.ln_Name)==0))
{
switch(optiontype)
{
case VTYPE_STRING:
case VTYPE_DATE:
if (*result!=NULL) LIBFreeStr(*result);
*result=(V_STRING *)LIBDupStr(Item->Params);
found++;
break;
case VTYPE_PATH:
if (*result!=NULL) LIBFreeStr(*result);
if (*result=(V_STRING)AllocVec(strlen(Item->Params)+1,MEMF_CLEAR|MEMF_PUBLIC))
{
strcpy((V_STRING)*result,Item->Params);
if ((Item->Params[strlen(Item->Params)-1]!='/') && (Item->Params[strlen(Item->Params)-1]!=':'))
{
strcat((V_STRING)*result,"/");
}
found++;
}
break;
case VTYPE_BOOL:
*result=(V_BOOL *)LIBCheckBoolean(Item->Params);
found++;
break;
case VTYPE_BIGNUM:
case VTYPE_TIME:
*result=(V_BIGNUM *)atoi(Item->Params);
found++;
break;
case VTYPE_WORD:
*result=(WORD *)atoi(Item->Params);
found++;
break;
case VTYPE_SMALLNUM:
*result=(V_SMALLNUM *)atoi(Item->Params);
found++;
break;
case VTYPE_STRINGLIST:
case VTYPE_PATHLIST:
// free existing stringlist if present
if ((found==0) && (*result))
{
LIBFreeStrList((V_STRINGLIST)*result);
}
if (!(*result))
{
if(*result=AllocVec(sizeof (struct List),MEMF_PUBLIC))
{
NewList((struct List*)*result);
}
}
if (*result) // allocated new list ok ?
{
if (node=AllocVec(sizeof(struct Node),MEMF_PUBLIC))
{
if (optiontype==VTYPE_PATHLIST)
{
if (node->ln_Name=AllocVec(strlen(Item->Params)+1,MEMF_CLEAR|MEMF_PUBLIC))
{
strcpy(node->ln_Name,Item->Params);
if ((node->ln_Name[strlen(node->ln_Name)-1]!=':') && (node->ln_Name[strlen(node->ln_Name)-1]!='/'))
{
strcat(node->ln_Name,"/");
}
}
}
else
{
node->ln_Name=LIBDupStr(Item->Params);
}
if (!(node->ln_Name))
{
FreeVec(node);
}
else
{
AddTail((struct List *)*result,node);
found++;
// go to start of list again or we might miss out something..
Item = (struct CfgItemData *)cfgfile->ItemsList->lh_Head;
}
}
}
}
}
}
FreeVec(CompareStr);
}
return(found);
}
struct CfgFileData __asm __saveds *LIBHBBS_CreateConfig(register __a0 UBYTE *filename)
{
struct CfgFileData *newcfg;
if (newcfg=(struct CfgFileData *)AllocVec(sizeof(struct CfgFileData),MEMF_PUBLIC|MEMF_CLEAR))
{
if (newcfg->ItemsList=(struct List *)AllocVec(sizeof(struct List ),MEMF_PUBLIC))
{
NewList(newcfg->ItemsList);
newcfg->filename=LIBDupStr(filename); // *C* add errorchecking..
}
else
{
FreeVec(newcfg);
newcfg=NULL;
}
}
return(newcfg);
}
BOOL __asm __saveds LIBHBBS_RemoveCfgItem(register __a0 struct CfgFileData *cfgfile,register __a1 UBYTE *itemname)
{
struct CfgItemData *node;
BOOL Removed=FALSE;
char *match;
if (match=AllocVec((strlen(itemname)*2)+2,MEMF_PUBLIC))
{
if (cfgfile && cfgfile->ItemsList)
{
for (node = (struct CfgItemData*)cfgfile->ItemsList->lh_Head ;(node->node.ln_Succ) ; node =(struct CfgItemData *)node->node.ln_Succ)
{
ParsePatternNoCase(itemname,match,(strlen(itemname)*2)+2);
if (MatchPatternNoCase(match,node->node.ln_Name))
{
Remove((struct Node*)node);
LIBFreeStr(node->Params);
LIBFreeStr(node->node.ln_Name);
FreeVec(node);
// go to start of list again..
node=node = (struct CfgItemData*)cfgfile->ItemsList->lh_Head;
Removed=TRUE;
}
}
}
FreeVec(match);
}
return(Removed);
}
BOOL __asm __saveds LIBHBBS_AddCfgItem(register __a0 struct CfgFileData *cfgfile,register __a1 UBYTE *itemname,register __a2 UBYTE *params)
{
struct CfgItemData *node;
BOOL Done=FALSE;
/*
char *offset,*remstr;
short loop;
*/
if (cfgfile && cfgfile->ItemsList)
{
// check to see if itemname is already there..
LIBHBBS_RemoveCfgItem(cfgfile,itemname);
/*
* Unsed bit of usefull code, was origonally going to make it so that when you start
* adding items of a list to a config items list it removed all the parts of the old
* list first.. but decided not to do it this way (at all) but left this bit of code
* cos it might be usefull.. :-)
*
if (offset=strrchr(itemname,'_'))
{
offset++;
if (offset[0]!=0)
{
if (isdigit(offset[0]))
{
loop=1;
while (isdigit(offset[loop]))
{
loop++;
}
if (offset[loop]==0)
{
if (remstr=AllocVec(strlen(itemname)+2,MEMF_PUBLIC))
{
LIBstrNcpy(remstr,itemname,offset-itemname);
strcat(remstr,"#?");
LIBHBBS_RemoveCfgItem(cfgfile,remstr);
FreeVec(remstr);
}
}
}
}
}
*/
if (node=AllocVec(sizeof(struct CfgItemData),MEMF_PUBLIC))
{
node->node.ln_Name=LIBDupStr(itemname); // *C* add errorchecking..
node->Params=LIBDupStr(params);
AddTail(cfgfile->ItemsList,(struct Node*)node);
Done=TRUE;
}
}
return(Done);
}
void __asm __saveds LIBHBBS_ResetNodeData(register __a0 struct NodeData *node)
{
// this function is called a) when a node is initialised
// and b) when a node shuts down. (everything is freed first tho..
node->LoginType=LOGIN_NONE;
node->OnlineStatus=OS_OFFLINE; // node program sets this to ONLINE or OFFLINE
// this shot be used in all door programs to determine
// carrier status (even for local logins..)
node->User.Valid=FALSE;
node->User.ConfAcs.Name=NULL;
node->NodeFlags=0L;
node->Status=STAT_CLOSED;
node->NodePort=NULL;
node->SettingsOpen=FALSE;
node->InformationOpen=FALSE;
node->ConOK=FALSE;
node->SerOK=FALSE;
node->SerOPEN=FALSE;
node->SerWaiting=FALSE;
node->ConWaiting=FALSE;
node->ReplyPort=NULL;
node->RequestShutdown=FALSE;
node->ActiveDoor=NULL;
node->DoorsRunning=0;
node->DoorReturn[0]=0;
node->CurrentLine[0]=0;
node->TransferringFile=FALSE;
node->TaggedFiles=0;
node->AllowLogins=TRUE;
strcpy(node->Action,"Initialising!"); // max 29 chars!
node->ConnectBaud[0]=0; // max 8 chars..
node->Current_Last_Callers=0;
node->Current_Last_Uploads=0;
node->Current_Last_Downloads=0;
node->Current_Last_PWFails=0;
node->Current_Last_Carrier=0;
node->Current_Last_Pagers=0;
// *C* make sysop definable..
node->Max_Last_Callers=10;
node->Max_Last_Uploads=10;
node->Max_Last_Downloads=10;
node->Max_Last_PWFails=10;
node->Max_Last_Carrier=10;
node->Max_Last_Pagers=10;
}
void __asm __saveds LIBHBBS_rterror(register __a0 char *str)
{
rtEZRequestTags(str,str_OK,NULL,NULL,RTGS_Flags, GSREQF_CENTERTEXT,TAG_END);
}
LONG __asm __saveds LIBHBBS_RunDOSCMD(register __a0 char *command,register __d0 BOOL ASYNC)
{
LONG retval;
char newcmd[BIG_STR],consolename[BIG_STR];
static ULONG sysargs[] =
{
SYS_Input,NULL,
SYS_Output,NULL,
SYS_Asynch,TRUE,
SYS_UserShell,TRUE,
NP_Priority,0L,
TAG_DONE
};
BPTR outputfile=NULL;
sysargs[5]=ASYNC;
LIBreplace(newcmd,command,"@S@",BBSGlobal->ScreenInfo.PubScreenName);
LIBreplace(consolename,str_CONSOLE,"@S@",BBSGlobal->ScreenInfo.PubScreenName);
// if (!strchr(newcmd,'>') && !strchr(newcmd,'<'))
// {
if (outputfile = Open(consolename,MODE_OLDFILE))
{
sysargs[1]=(ULONG)outputfile;
}
// }
retval=SystemTagList(newcmd,(struct TagItem *)sysargs);
if (!ASYNC && outputfile) Close(outputfile); // close window if not async
return(retval);
// *C* perhaps add a routine to close async'ed windows after 5 mins ??
}
void __asm __saveds LIBHBBS_DoErrorMessage(register __d0 ULONG num,register __d1 ULONG node,register __a0 char *errstr)
{
char *str;
int len=20; // 20 extra chars should be ok for the numbers
if (errstr) len+=strlen(errstr);
if (str=AllocVec(len+strlen(PRG_ERRORMESSAGE),MEMF_PUBLIC))
{
sprintf(str,"%s %d %d ",PRG_ERRORMESSAGE,num,node);
if (errstr) strcat(str,errstr);
LIBHBBS_RunDOSCMD(str,TRUE); // *C* false ?
FreeVec(str);
}
}
void __asm __saveds LIBcvtucase(register __a0 char *str)
{
int loop;
for (loop=0;str[loop]!=0;loop++)
{
str[loop]=toupper(str[loop]);
}
}
BOOL __asm __saveds LIBAssignOK(register __a0 char *checkme )
{
struct DosList *DosList;
struct DeviceNode *DevNode;
UBYTE *Pointer;
char string[32]="",cmpstring[32]="";
int loop;
BOOL found=FALSE;
if (strnicmp(checkme,"Progdir:",8)==0)
{
found=TRUE;
}
else
{
for (loop = 0 ; checkme[loop]!=0 && checkme[loop]!=':' && checkme[loop]!='/' ; loop++);
LIBstrNcpy(cmpstring,checkme,loop);// +1); // +1 cos we WANT the ':'
LIBcvtucase(cmpstring);
DosList = LockDosList(LDF_ALL|LDF_READ);
while((DosList = NextDosEntry(DosList,LDF_ALL|LDF_READ)) && !found)
{
DevNode = (struct DeviceNode *)DosList;
// assign or volume ?
if (DevNode->dn_Type==DLT_DIRECTORY || DevNode->dn_Type==DLT_DEVICE || DevNode->dn_Type==DLT_VOLUME)
{
Pointer = (UBYTE *)BADDR(DevNode -> dn_Name);
if (Pointer[0])
{
for(loop = 0 ; loop < Pointer[0] ; loop++)
string[loop] = Pointer[loop + 1];
string[Pointer[0]] = 0; /* terminate string */
// strcat(string,":");
LIBcvtucase(string);
if (strcmp(cmpstring,string)==0) found=TRUE;
}
}
}
UnLockDosList(LDF_ALL|LDF_READ);
}
return(found);
}
BOOL __asm __saveds LIBHBBS_InitCommon( void )
{
SysBase = *(struct ExecBase **) 4L;
if (DOSBase = (struct DosLibrary *) OpenLibrary ("dos.library", 0))
{
if (ReqToolsBase = (struct ReqToolsBase *) OpenLibrary (REQTOOLSNAME, REQTOOLSVERSION))
return(TRUE);
}
return(FALSE);
}
void __asm __saveds LIBHBBS_CleanUpCommon( void )
{
if (ReqToolsBase) CloseLibrary ((struct Library *)ReqToolsBase);
if (DOSBase) CloseLibrary ((struct Library *) DOSBase);
}
struct TimerData __asm __saveds *LIBSubmitTimer(register __a0 struct TimerSetupData *TSD, register __d0 ULONG Seconds,register __d1 ULONG MicroSeconds )
{
struct TimerData *TD=NULL;
if (TSD)
{
if (TD=(struct TimerData*)AllocVec(sizeof(struct TimerData),MEMF_PUBLIC))
{
// copy fields accross from our blank timer IO request
// that was initialised by InitTimer();
// Source Dest Size
CopyMem(TSD->BlankTimerIO,&TD->TR,sizeof(struct timerequest));
TD->TR.tr_time.tv_secs = Seconds;
TD->TR.tr_time.tv_micro = MicroSeconds;
AddHead(TSD->TimerList,(struct Node*)TD);
SendIO((struct IORequest *)&TD->TR);
}
}
return(TD);
}
void __asm __saveds LIBAbortTimer(register __a0 struct TimerSetupData *TSD, register __a1 struct TimerData *CTD)
{
struct TimerData *TD;
if (CTD)
{
for (TD = (struct TimerData *)TSD->TimerList->lh_Head ; TD->node.ln_Succ ; TD =(struct TimerData *) TD->node.ln_Succ)
{
if (TD==CTD)
{
AbortIO((struct IORequest *)&CTD->TR);
WaitIO((struct IORequest *)&CTD->TR);
Remove((struct Node*)CTD);
FreeVec(CTD);
// TD is now null so we dont wat to reference it again so return from the func..
return;
}
}
}
}
BOOL __asm __saveds LIBCheckTimer(register __a0 struct TimerSetupData *TSD, register __a1 struct TimerData *CTD)
{
struct TimerData *TD;
for (TD = (struct TimerData *)TSD->TimerList->lh_Head ; TD->node.ln_Succ ; TD =(struct TimerData *) TD->node.ln_Succ)
{
if (TD==CTD)
{
if (CheckIO((struct IORequest *)&CTD->TR))
{
WaitIO((struct IORequest *)&CTD->TR);
Remove((struct Node*)CTD);
FreeVec(CTD);
return(TRUE);
}
}
}
return(FALSE);
}
void __asm __saveds LIBCleanupTimer( register __a0 struct TimerSetupData *TSD )
{
struct TimerData *TD;
if (TSD)
{
if (TSD->TimerPort)
{
if (TSD->BlankTimerIO)
{
if (TSD->TimerOpen)
{
if (TSD->TimerList)
{
// remove all outstanding io requests..
while ((struct TimerData *)TSD->TimerList->lh_Head->ln_Succ)
{
TD=(struct TimerData *)TSD->TimerList->lh_Head;
AbortIO((struct IORequest *)&TD->TR);
WaitIO((struct IORequest *)&TD->TR);
Remove((struct Node*)TD);
FreeVec(TD);
}
FreeVec(TSD->TimerList);
}
CloseDevice((struct IORequest *) TSD->BlankTimerIO);
TSD->TimerOpen=FALSE;
}
DeleteExtIO((struct IORequest *) TSD->BlankTimerIO);
}
DeleteMsgPort(TSD->TimerPort);
}
FreeVec(TSD);
}
}
struct TimerSetupData __asm __saveds *LIBInitTimer( void )
{
struct TimerSetupData *TSD;
if (TSD=AllocVec(sizeof(struct TimerSetupData),MEMF_PUBLIC))
{
TSD->TimerOpen=FALSE;
if (TSD->TimerPort = CreateMsgPort())
{
if (TSD->BlankTimerIO = (struct timerequest *) CreateExtIO(TSD->TimerPort,sizeof(struct timerequest)) )
{
if (OpenDevice( TIMERNAME, UNIT_VBLANK,(struct IORequest *) TSD->BlankTimerIO, 0L)==0) // success ?
{
TSD->TimerOpen=TRUE;
TSD->BlankTimerIO->tr_node.io_Command = TR_ADDREQUEST;
if (TSD->TimerList=AllocVec(sizeof(struct List),MEMF_PUBLIC))
{
NewList((struct List *)TSD->TimerList);
return(TSD);
}
}
}
}
LIBCleanupTimer(TSD);
}
return(NULL);
}
BOOL __asm __saveds LIBPathOK(register __a0 char *str)
{
BPTR FL;
if (LIBAssignOK(str))
{
if (FL=Lock(str,ACCESS_READ))
{
UnLock(FL);
return(TRUE);
}
}
return(FALSE);
}
BOOL __asm __saveds LIBHBBS_LoadUser(register __d0 V_BIGNUM ID,register __a0 char *handle,register __a1 char *realname,register __a2 struct UserData *user)
{
// specify only one of ID,handle or realname
// "user" should already be allocated..
BPTR FH;
BPTR FL;
V_BOOL Found=FALSE;
if(user)
{
if (ID>0)
{
// keep trying.. *C* add error checking here to check existance of the file!
while (!(FL=Lock(BBSGlobal->UserDataFileName,ACCESS_READ)));
if (FH=OpenFromLock(FL))
{
if (Seek(FH,(ID-1)*sizeof(struct UserData),OFFSET_BEGINNING)!=-1)
{
if (Read(FH,user,sizeof(struct UserData))==sizeof(struct UserData))
{
Found=TRUE;
}
// else puts("Short Read!");
}
Close(FH);
}
// else puts("Error Opening Userdata file");
if (Found) return(TRUE);
}
else
{
if (handle!=NULL) // *C* Implement!
{
// printf("Searching for user with a handle of %s\n",handle);
}
else
{
if (realname!=NULL) // *C* Implement!
{
// printf("Searching for user with a realname of %s\n",realname);
}
}
}
}
return(FALSE);
}
V_BOOL __asm __saveds LIBHBBS_ValidUserHandle(register __a0 char *userhandle, register __a1 struct UserData *FillUser)
{
// Small routing to see if a user name does exist, if the user does
// exist and FillUser points an allocated data structure the size of
// sizeof(struct UserData) then the uses info that was found will be copied
// to there.
V_BIGNUM CurrentUserNum=0;
V_BOOL Found=FALSE;
struct UserData User;
if (BBSGlobal->TotalUsers>=0) // spose we better check this :-)
{
// *C* change me, TotalUsers DOES NOT REFLECT amount of users in the userdata file
// we just need a while loop that checks found and failure of HBBS_LoadUser
while (!Found && CurrentUserNum<BBSGlobal->TotalUsers)
{
CurrentUserNum++;
// printf("Searching %d For User \"%s\"\n",CurrentUserNum,userhandle);
if (LIBHBBS_LoadUser(CurrentUserNum,NULL,NULL,&User))
{
// *C* insert pattern matching routine here..
// or not ? perhps add an "Interactive Y/N" parameter.
if (stricmp(userhandle,User.Handle)==0)
{
Found=TRUE;
}
}
// else puts("Failed To Load User");
}
}
if (Found && FillUser)
{
CopyMem(&User,FillUser,sizeof (struct UserData));
}
return(Found);
}
V_BIGNUM __asm __saveds LIBHBBS_FindTotalUsers( void )
{
BPTR FL;
struct FileInfoBlock FB;
BBSGlobal->TotalUsers=-1;
// keep trying!
while (!(FL=Lock(BBSGlobal->UserDataFileName,ACCESS_READ)));
if (Examine(FL,&FB));
{
BBSGlobal->TotalUsers=(V_BIGNUM)(FB.fib_Size / sizeof(struct UserData));
}
UnLock(FL);
return(BBSGlobal->TotalUsers);
}
BOOL __asm __saveds LIBLoadPrivateData( void )
{
struct CfgFileData *PrivateCFG;
BOOL retval=FALSE;
if (PrivateCFG=LIBHBBS_LoadConfig(FILE_PRIVATEDATA,LCFG_NONE))
{
LIBHBBS_GetSetting(PrivateCFG,(void *)&BBSGlobal->CallsEver,VTYPE_BIGNUM,OPT_PRIV_CallsEver,OPT_SINGLE);
if (LIBHBBS_GetSetting(PrivateCFG,(void *)&BBSGlobal->LastUserNum,VTYPE_BIGNUM,OPT_PRIV_LastUserNum,OPT_SINGLE))
{
retval=TRUE;
}
LIBHBBS_FlushConfig(PrivateCFG);
}
return(retval);
}
void __asm __saveds LIBUpdatePrivateData ( void )
{
struct CfgFileData *PrivateCFG;
char str[BIG_STR];
if (PrivateCFG=LIBHBBS_CreateConfig(FILE_PRIVATEDATA))
{
sprintf(str,"%ld",BBSGlobal->CallsEver);
LIBHBBS_AddCfgItemQuick(PrivateCFG,OPT_PRIV_CallsEver,str);
sprintf(str,"%ld",BBSGlobal->LastUserNum);
LIBHBBS_AddCfgItemQuick(PrivateCFG,OPT_PRIV_LastUserNum,str);
LIBHBBS_SaveConfig(PrivateCFG);
LIBHBBS_FlushConfig(PrivateCFG);
}
}
BOOL __asm __saveds LIBHBBS_AddUser(register __a0 struct UserData *user)
{
// *C* need to add some checking/locking of file for multinode operation..
BPTR FH;
BPTR FL;
BOOL Saved=FALSE;
char dirname[BIG_STR],filenote[80];
// *C* need to check to see if file exists... (or get setup program to create..)
// get exclusive access to userdata file when writing..
while (!(FL=Lock(BBSGlobal->UserDataFileName,ACCESS_WRITE))); // keep trying..
if (FH=OpenFromLock(FL)) //(BBSGlobal->UserDataFileName,MODE_OLDFILE))
{
if (Seek(FH,0,OFFSET_END)!=-1)
{
BBSGlobal->LastUserNum++;
user->UserID=BBSGlobal->LastUserNum;
if (Write(FH,user,sizeof(struct UserData))==sizeof(struct UserData))
{
LIBUpdatePrivateData();
Saved=TRUE;
}
else
{
// puts("Error Adding Data To File, Truncating..");
if (SetFileSize(FH,OFFSET_BEGINNING,BBSGlobal->TotalUsers * sizeof(struct UserData))==-1)
{
// puts("Cound Not Truncate File!");
}
}
} // else puts("Seek() Failed!");
Close(FH);
}
else UnLock(FL);
if (Saved)
{
sprintf(filenote,"Handle: %s, Group: %s",user->Handle, user->Group);
sprintf(dirname,"HBBS:System/Data/Users/%d",user->UserID);
if (FL=CreateDir(dirname))
{
UnLock(FL);
SetComment(dirname,filenote);
}
sprintf(dirname,"HBBS:Mail/Users/%d",user->UserID);
if (FL=CreateDir(dirname))
{
UnLock(FL);
SetComment(dirname,filenote);
}
}
LIBHBBS_FindTotalUsers();
return(Saved);
}
struct Node __asm __saveds *LIBHBBS_FindNode(register __a0 struct List *list,register __a1 char *str)
{
struct Node *node,*retval=NULL;
V_BOOL found=FALSE;
if (list && str)
{
for (node=list->lh_Head;!found && node->ln_Succ;node=node->ln_Succ)
{
if (node->ln_Name)
{
if (stricmp(node->ln_Name,str)==0)
{
found=TRUE;
retval=node;
}
}
}
}
return(retval);
}
V_BIGNUM __asm __saveds LIBHBBS_FindNodeNum(register __a0 struct List *list, register __a1 char *str)
{
struct Node *node;
V_BIGNUM retval=-1;
if (node=LIBHBBS_FindNode(list,str))
{
retval=LIBGetNodeNum(list,node);
}
return(retval);
}
void __asm __saveds LIBHBBS_InitUserData(register __a0 struct UserData *User,register __d0 V_BIGNUM AccessLevel,register __d1 V_BIGNUM ConfNum)
{
struct Node *node;
char tmpstr[BIG_STR];
int num;
User->Status=USER_NEW;
User->Access=AccessLevel;
User->Handle[0]=0;
User->RealName[0]=0;
User->Group[0]=0;
User->GeoLocation[0]=0;
User->Country[0]=0;
User->PhoneNumber[0]=0;
User->Password[0]=0;
User->ComputerType[0]=0;
User->SentBy[0]=0;
User->ConfAcsDataFile[0]=0;
sprintf(tmpstr,"%d",AccessLevel);
if ((num=LIBHBBS_FindNodeNum(BBSGlobal->AcsLevelList,tmpstr))!=-1)
{
node=LIBGetNode(BBSGlobal->AcsLevelConfAcsDef,num);
strcpy(User->ConfAcsDataFile,node->ln_Name);
}
User->LeechAccDataFile[0]=0;
User->UploadBytes=0;
User->UploadFiles=0;
User->DownloadBytes=0;
User->DownloadFiles=0;
User->ActualUploadBytes=0;
User->ActualUploadFiles=0;
User->ActualDownloadBytes=0;
User->ActualDownloadFiles=0;
User->LastUploadDate=0; // *C* add HBBS_Todate() ?
User->LastCalledDate=0;
User->BestCPSUp=0;
User->BestCPSDown=0;
User->CallsMade=0;
User->PagesMade=0;
User->MessagesWritten=0;
User->FilesRatio=3;
User->BytesRatio=3;
User->LastConf=ConfNum;
User->PreferedConf=0;
User->LinesPerScreen=24;
User->Protocol=0; // ASK
User->Editor=0; // ASK
User->TimeAccessFile[0]=0;
User->ExtraTimeLimit=0;
User->ExtraBytesLimit=0;
User->ExtraCallsLimit=0;
User->ExtraChatLimit=0;
User->TimeUsed=0;
User->BytesUsed=0;
User->CallsUsed=0;
User->ChatUsed=0;
User->BytesAllowed=0;
User->TimeAllowed=0;
User->CallsAllowed=0;
User->ChatAllowed=0;
User->UserType=USERTYPE_NORMAL;
User->Language=0; // .TXT or the first one in the list..
}
void __asm __saveds LIBstrNcpy(register __a0 UBYTE *dest,register __a1 UBYTE *source,register __d0 int chars)
{
int count=0;
while ((dest[count]=source[count]) && count<chars-1) count++;
dest[count+1]=0;
}
char __asm __saveds *LIBHBBS_ListName(register __a0 V_STRINGLIST ListName,register __d0 V_SMALLNUM ItemNum)
{ //starts from offset 0, 0 being the first node in the list..
struct Node *node;
if(node=LIBGetNode(ListName,ItemNum))
{
return(node->ln_Name);
}
return(NULL);
}
void __asm __saveds LIBFreeFileTags( register __a0 struct NodeData *N_ND )
{
struct TaggedFile *tfnode;
while ((N_ND->TaggedFileList) && (N_ND->TaggedFileList->lh_Head->ln_Succ))
{
tfnode=(struct TaggedFile *)N_ND->TaggedFileList->lh_Head;
LIBFreeStr(tfnode->node.ln_Name);
Remove((struct Node*)tfnode);
FreeVec(tfnode);
}
N_ND->TaggedFiles=0;
}
/*
struct List __asm __saveds *LIBHBBS_LoadFile(register __a0 char *filename)
{
BPTR FL,FH;
LONG bufferpos;
BOOL done;
struct FileInfoBlock FB;
UBYTE *Data=NULL;
LONG Length=0,filepos=0;
UBYTE buffer[bufflen];
struct List *FileList=NULL;
if (FL=Lock(filename,ACCESS_READ))
{
if (Examine(FL,&FB))
{
if (FB.fib_Size)
{
if (Data=AllocVec(FB.fib_Size,MEMF_PUBLIC))
{
if (FH=OpenFromLock(FL))
{
Length=Read(FH,Data,FB.fib_Size);
Close(FH);
}
}
}
}
UnLock(FL);
if ((Data) && (Length>0))
{
if (FileList=LIBHBBS_CreateList())
{
do
{
bufferpos=0;
done=FALSE;
do
{
if (Data[filepos]==13) //cr
{
if ((filepos+1<Length) && (Data[filepos+1]==10)) // cr followed by lf ?
{
done=TRUE;
filepos++;//skip the lf too.
}
else
{
done=TRUE;
}
filepos++; //skip the cr
}
else
{
if (Data[filepos]==10) //lf
{
done=TRUE;
filepos++;
}
else
{
buffer[bufferpos]=Data[filepos];
filepos++;
bufferpos++;
}
}
} while (filepos<Length && !done && bufferpos<bufflen-2); // 1 for null and 1 more cos we still have to add the null
buffer[bufferpos]=0;
LIBNewStrNode(buffer,FileList);
} while (filepos<Length);
}
}
if (Data) FreeVec(Data);
}
return(FileList);
}
*/
#define bufflen 1024
struct List __asm __saveds *LIBHBBS_LoadFile(register __a0 char *filename)
{
/* New Optimized Version: 4-JAN-1996 */
BPTR FH;
UBYTE buffer[bufflen];
struct List *FileList=NULL;
BOOL error=FALSE;
if (LIBPathOK(filename))
{
if (FH=Open(filename,MODE_OLDFILE))
{
if (FileList=LIBHBBS_CreateList())
{
while (FGets(FH,buffer,bufflen) && !error)
{
LIBstripcr(buffer);
if (LIBNewStrNode(buffer,FileList))
{
error=TRUE;
}
}
}
Close(FH);
}
}
if (error)
{
LIBFreeStrList(FileList);
FileList=NULL;
}
return(FileList);
}
BOOL __asm __saveds LIBHBBS_SaveFile( register __a0 char *file_name, register __a1 struct List *list)
{
BPTR FH;
struct Node *node;
if (FH=Open(file_name,MODE_NEWFILE))
{
for (node = list->lh_Head ; node->ln_Succ ; node =node->ln_Succ)
{
Write(FH,node->ln_Name,strlen(node->ln_Name));
Write(FH,"\n",1); //add cr+lf
}
Close(FH);
}
return((BOOL)(FH ? TRUE : FALSE));
}
struct List __asm __saveds *LIBHBBS_CreateList( void )
{
struct List *NList;
if (NList=AllocVec(sizeof(struct List),MEMF_PUBLIC))
{
NewList(NList);
}
return(NList);
}
void __asm __saveds LIBstrftcpy(register __a0 char *dest,register __a1 char *source,register __d0 int from,register __d1 int topos)
{
int loop=from,pos=0;
if (from<=strlen(source)-1)
{
while (source[loop] && loop<=topos)
{
dest[pos]=source[loop];
loop++;
pos++;
}
}
dest[pos]=0;
}
void __asm __saveds LIBRemoveSpaces(register __a0 char *string)
{
// removes spaces from the start end end of strings
ULONG start,end,len;
if (string)
{
len=strlen(string);
for (start=0;string[start]==' ';start++);
for (end=len-1;string[end]==' ';end--);
LIBstrftcpy(string,string,start,end);
}
}
void __asm __saveds LIBHBBS_SaveUserData(register __a0 struct UserData *User)
{
// *C* here we should save the data in N_ND->User.NormalData
// back to the user file..
BPTR FH,FL;
BOOL Found,ReadError=FALSE;
struct UserData OldUser;
while (!(FL=Lock(BBSGlobal->UserDataFileName,ACCESS_WRITE)));
if (FH=OpenFromLock(FL))
{
Found=FALSE;
while (!Found && !ReadError)
{
// keep going until the end of the file or we get a read error..
ReadError=((Read(FH,&OldUser,sizeof(struct UserData))==sizeof(struct UserData)) ? FALSE : TRUE );
if (!ReadError)
{
if (OldUser.UserID==User->UserID)
{
Found=TRUE;
}
}
}
if (Found)
{
// *C* if error on next to commands then loop until it works ?
// seek to start of record.
Seek(FH,0-sizeof(struct UserData),OFFSET_CURRENT);
Write(FH,User,sizeof(struct UserData));
}
Close(FH);
}
else UnLock(FL);
}
void __asm __saveds LIBHBBS_GetDate(register __a0 char *datestr)
{
struct tm *timestruct;
long t;
if (datestr)
{
time(&t);
timestruct=localtime(&t);
LIBHBBS_DateStrFromTM(datestr,timestruct);
/*
sprintf(datestr,"%s%d-%s-%-04d",(timestruct->tm_mday < 10) ? "0" : "",timestruct->tm_mday,monthstr[timestruct->tm_mon],timestruct->tm_year + 1900);
*/
}
free(timestruct);
}
V_BOOL __asm __saveds LIBHBBS_AddCfgItemQuick(register __a0 struct CfgFileData *cfgfile,register __a1 char *ItemName, register __a2 char *Params)
{
struct CfgItemData *node;
V_BOOL retval=FALSE;
if (cfgfile && ItemName && Params)
{
if (node=AllocVec(sizeof(struct CfgItemData),MEMF_PUBLIC))
{
node->node.ln_Name=LIBDupStr(ItemName); // *C* error check me! (or not ?)
node->Params=LIBDupStr(Params);
AddTail(cfgfile->ItemsList,(struct Node*)node);
retval=TRUE;
}
}
return(retval);
}
void __asm __saveds LIBHBBS_SaveCallsData( void )
{
struct CfgFileData *CfgFile;
struct NodeData *nd;
UBYTE tmpstr[200],optionstr[200];
if (CfgFile=LIBHBBS_CreateConfig("HBBS:System/Data/Calls.CFG"))
{
LIBHBBS_GetDate(tmpstr);
LIBHBBS_AddCfgItemQuick(CfgFile,"Today",tmpstr);
sprintf(tmpstr,"%d",BBSGlobal->CallsToday);
LIBHBBS_AddCfgItemQuick(CfgFile,"TotalCalls",tmpstr);
for (nd=(struct NodeData *)BBSGlobal->NodeList->lh_Head;nd->node.ln_Succ;nd=(struct NodeData *)nd->node.ln_Succ)
{
sprintf(optionstr,"Node_%d_Calls",nd->NodeNum);
sprintf(tmpstr,"%d",nd->CallsToday);
LIBHBBS_AddCfgItemQuick(CfgFile,optionstr,tmpstr);
}
LIBHBBS_SaveConfig(CfgFile);
LIBHBBS_FlushConfig(CfgFile);
}
}
void __asm __saveds LIBHBBS_LoadCallsData( void )
{
struct CfgFileData *CfgFile;
BOOL Loaded=FALSE;
V_STRING TodayStr=NULL;
UBYTE tmpstr[200];
struct NodeData *nd;
LIBHBBS_GetDate(tmpstr);
if (CfgFile=LIBHBBS_LoadConfig("HBBS:System/Data/Calls.CFG",LCFG_NONE))
{
if (LIBHBBS_GetSetting(CfgFile,(void *)&TodayStr,VTYPE_STRING,"Today",OPT_SINGLE))
{
if (stricmp(TodayStr,tmpstr)==0) // same day ???
{
if (LIBHBBS_GetSetting(CfgFile,(void *)&BBSGlobal->CallsToday,VTYPE_BIGNUM,"TotalCalls",OPT_SINGLE))
{
for (nd=(struct NodeData *)BBSGlobal->NodeList->lh_Head;nd->node.ln_Succ;nd=(struct NodeData *)nd->node.ln_Succ)
{
sprintf(tmpstr,"Node_%d_Calls",nd->NodeNum);
if (!LIBHBBS_GetSetting(CfgFile,(void *)&nd->CallsToday,VTYPE_BIGNUM,tmpstr,OPT_SINGLE))
{
nd->CallsToday=0;
}
}
Loaded=TRUE;
}
}
}
}
if (!Loaded)
{
BBSGlobal->CallsToday=0;
for (nd=(struct NodeData *)BBSGlobal->NodeList->lh_Head;nd->node.ln_Succ;nd=(struct NodeData *)nd->node.ln_Succ)
{
nd->CallsToday=0;
}
LIBHBBS_SaveCallsData();
}
if (TodayStr) LIBFreeStr(TodayStr);
}
void __asm __saveds LIBHBBS_GetTime(register __a0 char *timestr)
{
struct tm *timestruct;
long t;
if (timestr)
{
time(&t);
timestruct=localtime(&t);
sprintf(timestr,"%s%d:%s%d:%s%d",(timestruct->tm_hour < 10) ? "0" : "",timestruct->tm_hour,
(timestruct->tm_min < 10) ? "0" : "",timestruct->tm_min,
(timestruct->tm_sec < 10) ? "0" : "",timestruct->tm_sec);
}
free(timestruct);
}
void __asm __saveds LIBHBBS_GetDateStr(register __a0 char *datestr,register __d0 long t)
{
long tt=t;
struct tm *timestruct;
if (datestr)
{
timestruct=localtime(&tt);
/*
if (timestruct->tm_mday<0)
{
strcpy(datestr,"01-JAN-1970"); // date limit!
}
else
{
sprintf(datestr,"%s%d-%s-%-04d",(timestruct->tm_mday < 10) ? "0" : "",timestruct->tm_mday,monthstr[timestruct->tm_mon],timestruct->tm_year+1900);
}
*/
LIBHBBS_DateStrFromTM(datestr,timestruct);
free(timestruct);
}
}
void __asm __saveds LIBHBBS_DateStrFromTM(register __a0 UBYTE *datestr, register __a1 struct tm *timestruct)
{
if (datestr && timestruct)
{
if (timestruct->tm_mday<0)
{
strcpy(datestr,"01-JAN-1970"); // date limit!
}
else
{
sprintf(datestr,"%s%d-%s-%-04d",(timestruct->tm_mday < 10) ? "0" : "",timestruct->tm_mday,monthstr[timestruct->tm_mon],timestruct->tm_year+1900);
}
}
}
V_BOOL __asm __saveds LIBHBBS_DateStrToTM(register __a0 UBYTE *datestr, register __a1 struct tm *timestruct)
{
UBYTE tmpstr[5];
LONG tday,tmon=-1,tyear,loop;
LIBstrNcpy(tmpstr,datestr,2);
if (sscanf(tmpstr,"%ld",&tday))
{
LIBstrftcpy(tmpstr,datestr,3,5);
for (loop=0;loop<=12 && tmon==-1;loop++)
{
if (stricmp(tmpstr,monthstr[loop])==0)
{
tmon=loop;
}
}
if (tmon>=0)
{
LIBstrftcpy(tmpstr,datestr,7,10);
if (sscanf(tmpstr,"%ld",&
tyear))
{
tyear-=1900;
if ((tyear>=70) && (tmon>=0) && (tmon<12) && (tday>=1) && (tday<=31))
{
// all data is ok, so opy it to the timestruct!
timestruct->tm_mday=tday;
timestruct->tm_year=tyear;
timestruct->tm_mon=tmon;
return(TRUE);
}
}
}
}
return(FALSE);
}
void *AllocBuffer(ULONG *BufferSize,ULONG Flags) // min 10 bytes!
{
void *retval=NULL;
if (*BufferSize)
{
if (*BufferSize<10) *BufferSize=10;
while ((*BufferSize>10) && ((retval=AllocVec(*BufferSize,Flags))==NULL))
{
*BufferSize/=2; // divide buffersize by 2!
}
}
return(retval);
}
V_BOOL __asm __saveds LIBHBBS_CopyFile(register __a0 char *fromfile, register __a1 char *tofile,register __d0 ULONG BufSize)
{
BOOL retval=FALSE;
BPTR FL,FromFH,ToFH;
struct FileInfoBlock FB;
BOOL error=TRUE;
ULONG nr,nw,total=0;
UBYTE *Buffer;
ULONG MyBufSize=BufSize;
if (MyBufSize==0) MyBufSize=BBSGlobal->CopyBufferSize; // *C* user selectable!
if (FL=Lock(fromfile,ACCESS_READ))
{
if (Examine(FL,&FB))
{
if (FromFH=OpenFromLock(FL))
{
if (ToFH=Open(tofile,MODE_NEWFILE))
{
if (FB.fib_Size>0)
{
if (MyBufSize>FB.fib_Size) MyBufSize=FB.fib_Size; // no sense allocating to much mem
if (Buffer=AllocBuffer(&MyBufSize,MEMF_PUBLIC))
{
do
{
error=FALSE;
if (nr=Read(FromFH,Buffer,MyBufSize-1))
{
if (nr==(nw=Write(ToFH,Buffer,nr)))
{
total+=nw;
} else error=TRUE;
} else error=TRUE;
} while (!error);
if (error && total>=FB.fib_Size) error=FALSE; //end of file rather than error...
FreeVec(Buffer);
}
}
else
{
error=FALSE;
}
Close(ToFH);
SetComment(tofile,FB.fib_Comment);
SetProtection(tofile,FB.fib_Protection);
}
Close(FromFH);
FL=NULL;
}
}
if (FL) UnLock(FL);
}
if (!error)
{
retval=TRUE;
// if (FL=Lock(tofile,ACCESS_READ)) // is the new file the same as the old one ?
// {
// total=FB.fib_Size;
// if (Examine(FL,&FB) && total==FB.fib_Size) retval=TRUE;
// UnLock(FL);
// }
}
if (!retval) // if the old file is different then delete it..
{
DeleteFile(tofile);
}
return(retval);
}
ULONG __asm __saveds LIBHBBS_NodesInList(register __a0 struct List *list)
{
struct Node *node;
ULONG Nodes=0;
if (list)
{
for (node=list->lh_Head;node->ln_Succ;node=node->ln_Succ)
{
Nodes++;
}
return(Nodes);
}
return(0);
}
V_BOOL __asm __saveds LIBHBBS_AppendStrToFile(register __a0 UBYTE *FileName, register __a1 UBYTE *String)
{
BPTR FH;
V_BOOL retval=FALSE;
if (LIBAssignOK(FileName))
{
if (FH=Open(FileName,MODE_READWRITE))
{
Seek(FH,0,OFFSET_END);
if (Write(FH,String,strlen(String))==strlen(String)) retval=TRUE;
Close(FH);
}
}
return(retval);
}
/*
HBBS_CreateNode() creates a node and returns a pointer to it.
if namestr is not NULL then the a new string will be allocated and
placed the ln_Name field.
if you specify 0 for the nodesize, then the size of the node allocated
will be the sizeof(struct Node), otherwise it'll allocate however many bytes
you specify.
All the data will be zero'd, so all your other fields will be intialized to NULL
or 0!
*/
struct Node __asm __saveds *LIBHBBS_CreateNode(register __a0 char *namestr,register __d0 ULONG nodesize)
{
struct Node *newnode;
if (nodesize==0) nodesize=sizeof(struct Node);
if (newnode=AllocVec(nodesize,MEMF_CLEAR|MEMF_PUBLIC))
{
if (namestr)
{
if (!(newnode->ln_Name=LIBDupStr(namestr)))
{
FreeVec(newnode);
newnode=NULL; // failed!
}
}
}
return(newnode); // NULL if not enough mem, or pointer to node otherwise..
}
void __asm __saveds LIBHBBS_FreeNode(register __a0 struct Node *node,register __d0 V_BOOL RemoveIt)
{
if (node)
{
if (RemoveIt) Remove(node);
if (node->ln_Name) LIBFreeStr(node->ln_Name);
FreeVec(node);
}
}
void __asm __saveds LIBHBBS_FreeListNodes(register __a0 struct List *list)
{
// free all ln_Names of each node in a list and remove all nodes from the list!
// but we DON't free the list itself, we just leave it empty
struct Node *node;
if (list)
{
while (list->lh_Head->ln_Succ)
{
node=list->lh_Head;
LIBFreeStr(node->ln_Name);
Remove(node);
FreeVec(node);
}
}
}
V_BOOL __asm __saveds LIBHBBS_SendOLM(register __d0 V_SMALLNUM FromNode,register __a0 UBYTE *FromPRG,register __d1 V_SMALLNUM ToNode,register __a1 UBYTE *Message,register __d2 BYTE Pri)
{
// frommnode should be 0 if something other than a door is sending the OLM
// otheriwse fromnode should be set to your node number plus 1
// e.g. N_ND->NodeNum+1, if fromnode
V_BOOL retval=FALSE;
struct OLMNode *NewOLM;
struct NodeData *nd;
struct NodeData *fnd;
struct Message *NewMsg;
// lets see if we can send an eall, node must be open and initalised with
// a user loggined in and the status must be online
if ((Message) &&
(FromNode>=0 ) && (FromNode<=BBSGlobal->BBSNodes) &&
(nd=LIBHBBS_NodeDataPtr(ToNode)) &&
(nd->Status==STAT_ONLINE) &&
(nd->OLMList) &&
(nd->LoginType!=LOGIN_NONE) &&
(nd->OnlineStatus==OS_ONLINE))
{
if (NewOLM=(struct OLMNode *)LIBHBBS_CreateNode(Message,sizeof(struct OLMNode)))
{
if (NewOLM->node.ln_Name=LIBDupStr(Message))
{
NewOLM->node.ln_Pri=Pri;
LIBHBBS_GetTime(NewOLM->Time);
LIBHBBS_GetDate(NewOLM->Date);
NewOLM->FromNode=FromNode;
if ((FromNode) && (fnd=LIBHBBS_NodeDataPtr(FromNode-1)))
{
if (fnd->User.Valid) // NewOLD has already been blanked by CreateNode() so the string is already null terminated..
{
LIBstrNcpy(NewOLM->Handle,fnd->User.CallData.Handle,LEN_HANDLE);
}
}
if (FromPRG)
{
LIBstrNcpy(NewOLM->FromPRG,FromPRG,LEN_HANDLE);
}
// *C* add semaphore checking!
Enqueue(nd->OLMList,(struct Node*)NewOLM);
nd->OLMCount++;
if (!(nd->NodeFlags & NFLG_OLMSWAITING)) nd->NodeFlags+=NFLG_OLMSWAITING;
if (nd->OLMPort)
{
if (NewMsg=AllocVec(sizeof (struct Message),MEMF_PUBLIC|MEMF_CLEAR))
{
NewMsg->mn_Node.ln_Type = NT_MESSAGE;
NewMsg->mn_ReplyPort=NULL;
NewMsg->mn_Length=sizeof(struct Message);
PutMsg(nd->OLMPort,NewMsg);
}
}
retval=TRUE;
}
}
}
return(retval);
}
BOOL __asm __saveds LIBFGetsR(register __a0 BPTR FH,register __a1 UBYTE *Buffer,register __d0 LONG BufferLen)
{
// fucking amazing routine to read a file line by line but BACKWARDS from the current
// position!! Whay!!
LONG nr,where,back,foundpos=0;
BOOL retval=TRUE,sof=FALSE,error=FALSE;
UBYTE *strptr=NULL;
Buffer[0]=0;
BufferLen--;
where=Seek(FH,0,OFFSET_CURRENT); // start of file already ?
if (where<=0) //start of file or error
{
retval=FALSE;
}
else
{
do
{
back=255;
if (where<255) back=where;
if (back>BufferLen) back=BufferLen;
if ((where=Seek(FH,0-back,OFFSET_CURRENT))!=-1)
{
where-=back;
if (nr=Read(FH,Buffer,back))
{
Buffer[nr]=0;
if (strptr=strrchr(Buffer,'\n'))
{
foundpos=where+(strptr-Buffer);
if (Seek(FH,foundpos+1,OFFSET_BEGINNING)==-1)
{
error=TRUE;
}
}
else
{
if (where==0)
{
if (Seek(FH,0,OFFSET_BEGINNING)==-1)
{
error=TRUE;
}
else
{
sof=TRUE;
foundpos=1;
}
}
else
{
if (Seek(FH,0-nr,OFFSET_CURRENT)!=-1)
{
where-=nr;
}
else
{
error=TRUE;
}
}
}
}
else
{
error=TRUE;
}
}
} while (strptr==NULL && !error && !sof);
Buffer[0]=0;
if (strptr || sof )
{
FGets(FH,Buffer,BufferLen);
Seek(FH,foundpos ? foundpos-1 : 0,OFFSET_BEGINNING);
}
}
return(retval);
}
V_BOOL __asm __saveds LIBHBBS_HandleNameOK(register __a0 char *checkstr)
{
if (strchr(checkstr,',')) return(FALSE);
if (strchr(checkstr,';')) return(FALSE);
if (strchr(checkstr,'?')) return(FALSE);
if (strchr(checkstr,'*')) return(FALSE);
if (strchr(checkstr,'#')) return(FALSE); // *C* optimze me..
if (strchr(checkstr,'(')) return(FALSE);
if (strchr(checkstr,')')) return(FALSE);
return(TRUE);
}